/**
 * 
 */
package com.xjt.common;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;

/**
 * @author Jet Xu
 * 
 */
public class FileUtils {
    /** 换行 */
    public static final String LINE_SEPARATOR = System.getProperty("line.separator");

    /** 读取文件的最大值 */
    public static final long MAX_STATIC_FILE_SIZE = 20 * 1024 * 1024;

    /** 每次读取的缓存大小 */
    public static final int BUFFER_SIZE = 20 * 1024;

    /** 日志类 */
    private static Logger log = Logger.getLogger(FileUtils.class);

    /**
     * 获取文件内容，以字符串返回
     * 
     * @param basePath 目录
     * @param fileName 文件名
     * @return
     * @throws IOException
     */
    public static String getFileContent(String basePath, String fileName) throws IOException {
        return getFileContent(getFile(basePath, fileName));
    }

    /**
     * 获取文件内容，以字符串返回
     * 
     * @param file
     * @return
     * @throws IOException
     */
    public static String getFileContent(File file) throws IOException {
        // 获取文件行列表
        List<String> list = getFileLineList(file);

        if (null == list) {
            return null;
        }

        StringBuilder sb = new StringBuilder(80);

        // 遍历文件行列表
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i)).append(LINE_SEPARATOR);
        }

        return sb.toString();
    }

    /**
     * 获取文件行列表
     * 
     * @param basePath 目录
     * @param fileName 文件名
     * @return
     * @throws IOException
     */
    public static List<String> getFileLineList(String basePath, String fileName) throws IOException {
        return getFileLineList(getFile(basePath, fileName));
    }

    /**
     * 获取文件行列表
     * 
     * @param file
     * @return
     * @throws IOException
     */
    public static List<String> getFileLineList(File file) throws IOException {
        if (null == file || !file.exists() || !file.isFile()) {
            return null;
        }

        // 如果超出文件可读的最大值
        if (file.length() > MAX_STATIC_FILE_SIZE) {
            return null;
        }

        List<String> list = new ArrayList<String>();

        BufferedReader br = new BufferedReader(new FileReader(file));

        String line = null;

        while ((line = br.readLine()) != null) {
            list.add(line);
        }

        close(br);

        return list;
    }

    /**
     * 生成文件
     * 
     * @param basePath 文件路径
     * @param fileName 文件名
     * @param lines 行
     * @param append 追加/覆盖
     * @throws IOException
     */
    public static boolean writeFile(String basePath, String fileName, List<String> lines, boolean append)
            throws IOException {
        StringBuilder sBuilder = new StringBuilder(1000);

        // 如果内容不为空，则拼接起来
        if (CollectionUtils.isNotEmpty(lines)) {
            for (int i = 0; i < lines.size(); i++) {
                sBuilder.append(lines.get(i)).append(LINE_SEPARATOR);
            }
        }

        return writeFile(basePath, fileName, sBuilder.toString(), append);
    }

    /**
     * 生成文件
     * 
     * @param basePath 文件路径
     * @param fileName 文件名
     * @param content 文件内容
     * @param append 追加/覆盖
     * @return
     * @throws IOException
     */
    public static boolean writeFile(String basePath, String fileName, String content, boolean append)
            throws IOException {
        // 如果内容为null或者超出最大值
        if (null == content || content.length() > MAX_STATIC_FILE_SIZE) {
            return false;
        }

        // 如果创建目录失败，则直接诶返回
        if (!createFolder(basePath)) {
            return false;
        }

        // 创建文件
        File file = createFile(basePath, fileName);

        // 如果创建文件失败，则直接诶返回
        if (null == file) {
            return false;
        }

        BufferedWriter write = new BufferedWriter(new FileWriter(file, append));

        // 开始写
        write.write(content);
        // 输出到硬盘
        write.flush();
        // 关闭输出流
        close(write);

        return true;
    }

    /**
     * 获取文件/目录
     * 
     * @param basePath 目录
     * @param fileName 文件名
     * @return
     */
    public static File getFile(String basePath, String fileName) {
        // 如果文件名为空，则直接返回
        if (StringUtils.isEmpty(fileName)) {
            return null;
        }

        File file;

        // 如果目录文件，则使用相对路径
        if (StringUtils.isEmpty(basePath)) {
            file = new File(fileName);
        }
        else {
            file = new File(basePath, fileName);
        }

        return file;
    }

    /**
     * 创建文件
     * 
     * @param basePath 目录
     * @param fileName 文件名
     * @return
     */
    public static File createFile(String basePath, String fileName) {
        File file = getFile(basePath, fileName);

        // 判断文件/目录是否存在，如果存在
        if (file.exists()) {
            // 如果不是文件，则直接返回null
            if (!file.isFile()) {
                return null;
            }
            // 如果不是文件，则直接返回文件
            else {
                return file;
            }
        }

        try {
            // 如果创建失败，则直接返回null
            if (!file.createNewFile()) {
                return null;
            }

            return file;
        }
        catch (IOException e) {
            // 如果创建出错，则直接返回null
            return null;
        }
    }

    /**
     * 创建目录
     * 
     * @param path
     */
    public static boolean createFolder(String path) {
        // 如果路径为空，则返回失败
        if (StringUtils.isEmpty(path)) {
            return false;
        }

        File folder = new File(path);

        // 判断文件/目录是否存在
        if (folder.exists()) {
            // 如果不是目录，则重命名
            if (!folder.isDirectory()) {
                // 如果重命名失败，则直接返回
                if (!folder.renameTo(new File(folder.getParent(), folder.getName() + "." + System.currentTimeMillis()))) {
                    return false;
                }
                folder = new File(path);
            }
            // 如果是目录，则直接返回
            else {
                return true;
            }
        }

        // 如果创建失败，则打印日志并返回
        if (!folder.mkdirs()) {
            // log sth.
            return false;
        }

        return true;

    }

    /**
     * 复制文件
     * 
     * @param srcFile 源文件
     * @param descFile 目标文件
     * @param isCover 是否覆盖
     * @return
     */
    public static int copyFile(File srcFile, File descFile, boolean isCover) {
        // 如果源文件不是为文件或不存在，则直接返回
        if (!isFileAndExist(srcFile)) {
            return States.SRC_FILE_NOT_EXIST;
        }

        // 如果源文件为null，则直接返回
        if (null == descFile) {
            return States.DEST_FILE_ERROR;
        }

        // 如果目标文件存在，且不能覆盖，则直接返回
        if (descFile.exists() && !isCover) {
            return States.DEST_FILE_EXIST;
        }

        InputStream is = null;
        OutputStream os = null;

        try {
            is = new BufferedInputStream(new FileInputStream(srcFile), BUFFER_SIZE);
            os = new BufferedOutputStream(new FileOutputStream(descFile), BUFFER_SIZE);

            byte[] buffer = new byte[BUFFER_SIZE];
            int len = 0;

            while ((len = is.read(buffer)) > 0) {
                os.write(buffer, 0, len);
            }
        }
        catch (Exception e) {
            log.error("", e);
            return States.FILE_COPY_OTHER_ERROR;
        }
        finally {
            try {
                // 关闭输入流
                close(is);
                // 关闭输出流
                close(os);
            }
            catch (IOException e) {
                log.error("", e);
                return States.FILE_COPY_OTHER_ERROR;
            }
        }

        return States.FILE_COPY_SUCCESS;
    }

    /**
     * 判断是否为文件且存在
     * 
     * @param srcFile
     * @return
     */
    public static boolean isFileAndExist(File srcFile) {
        return (null != srcFile) && (srcFile.exists()) && (srcFile.isFile());
    }

    /**
     * 关闭输入流
     * 
     * @param reader
     * @throws IOException
     */
    public static void close(Reader reader) throws IOException {
        if (null != reader) {
            reader.close();
        }
    }

    /**
     * 关闭输入流
     * 
     * @param reader
     * @throws IOException
     */
    public static void close(InputStream reader) throws IOException {
        if (null != reader) {
            reader.close();
        }
    }

    /**
     * 关闭输出流
     * 
     * @param reader
     * @throws IOException
     */
    public static void close(Writer writer) throws IOException {
        if (null != writer) {
            writer.close();
        }
    }

    /**
     * 关闭输出流
     * 
     * @param reader
     * @throws IOException
     */
    public static void close(OutputStream writer) throws IOException {
        if (null != writer) {
            writer.close();
        }
    }

    public static void main(String[] args) {

    }
}
